package org.dromara.school.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.enums.SchoolType;
import org.dromara.common.core.enums.UserType;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.SchoolUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.school.domain.*;
import org.dromara.school.domain.bo.ClassesBo;
import org.dromara.school.domain.bo.TeacherClassesBo;
import org.dromara.school.domain.vo.ClassesVo;
import org.dromara.school.domain.bo.SchoolClassesTreeNodeBo;
import org.dromara.school.service.*;
import org.dromara.system.domain.SysTenant;
import org.dromara.system.domain.vo.SysTenantVo;
import org.dromara.system.service.ISysTenantService;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.dromara.school.mapper.ClassesMapper;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 班级管理Service业务层处理
 *
 * @author Gjb
 * @date 2025-05-29
 */
@RequiredArgsConstructor
@Service
public class ClassesServiceImpl  extends MPJBaseServiceImpl<ClassesMapper, Classes> implements IClassesService {

    private final ClassesMapper baseMapper;

    private final ITeacherService teacherService;
    private final ICampusService campusService;

    private final ITeacherClassesService  teacherClassesService;

    private final ISysTenantService tenantService;

    private final IBindingSchoolsService bindingSchoolsService;



    /**
     * 查询班级管理
     */
    @Override
    public ClassesVo queryById(Long id){

        Classes classes = this.baseMapper.selectById(id);
        ClassesVo classesVo = new ClassesVo();
        BeanUtils.copyProperties(classes, classesVo);

        MPJLambdaWrapper<TeacherClasses> mpj = new MPJLambdaWrapper<TeacherClasses>()
            .selectAll(TeacherClasses.class)
            .eq(TeacherClasses::getClassesId, id)
            .logicDelToOn();
        List<TeacherClasses> teacherClasses = teacherClassesService.selectJoinList(TeacherClasses.class, mpj);
        if (teacherClasses.size() > 0) {
            classesVo.setClassTeachers(teacherClasses.stream().map(i -> i.getTeacherId()).collect(Collectors.toList()));
        }

        return classesVo;

    }

    /**
     * 查询班级管理列表
     */
    @Override
    public TableDataInfo<ClassesVo> queryPageList(ClassesBo bo, PageQuery pageQuery) {
        MPJLambdaWrapper<Classes> mpj = JoinWrappers.lambda(Classes.class)
            .selectAll(Classes.class)
            .selectAs(Teacher::getTeacherName,ClassesBo::getTeacherName)
            .leftJoin(Teacher.class, Teacher::getTeacherId, Classes::getTeacherId)
            .selectAs(Campus::getCampusName, ClassesBo::getCampusName)
            .leftJoin(Campus.class, Campus::getCampusId, Classes::getSchoolCampusId)
            .logicDelToOn()
            .orderByDesc(Campus::getCampusName)
            .orderByDesc(Classes::getClassYear)
            .orderByAsc(Classes::getClassNum);


        if (bo.getSchoolCampusId() != null) {
            mpj.eq(Classes::getSchoolCampusId, bo.getSchoolCampusId());
        }


        LoginUser loginUser = LoginHelper.getLoginUser();
        UserType userType = UserType.getUserType(loginUser.getUserType());

        switch (userType) {
            case SYS_USER:
                break;


            case SCHOOLADMIN:

//                List<Integer> campusids = Arrays.asList(loginUser.getSysUser().getSchoolCampusIds().split(",")).stream().map(i -> Integer.valueOf(i)).collect(Collectors.toList());
//                mpj.in(Classes::getSchoolCampusId, campusids);
                break;
//            case TEACHER:
////                List<Integer> campusids = Arrays.asList(loginUser.getSysUser().getSchoolCampusIds().split(",")).stream().map(i -> Integer.valueOf(i)).collect(Collectors.toList());
////                mpj.in(Classes::getSchoolCampusId, campusids);
//                break;
            case TEACHER:
                List<Object> t1 = this.teacherClassesService.findbyTeacherId(loginUser.getTeacherId());
                List<Object> t2 = this.findbyTeacherId(loginUser.getTeacherId());
                t1.addAll(t2);

                if (t1.size() > 0) {
                    mpj.selectAll(Classes.class)
                        .in(Classes::getId, t1);
                }else{
                    return null;
                }
                break;
            default:
                return null;
        }


        IPage<ClassesVo> ipage = baseMapper.selectJoinPage(
            new Page<ClassesVo>(pageQuery.getPageNum(), pageQuery.getPageSize()),
            ClassesVo.class, mpj
        );


        changeYearToName(ipage.getRecords());
        //数据列表
//        List<ClassesVo> items = ipage.getRecords();
//        //记录总数
//        long total = ipage.getTotal();

        TableDataInfo<ClassesVo> classesResult = TableDataInfo.build(ipage);


        return classesResult;

    }

    /**
     * 查询班级管理列表
     */
    @Override
    public List<ClassesVo> queryList(ClassesBo bo) {
        LambdaQueryWrapper<Classes> lqw = buildQueryWrapper(bo);
        return baseMapper.selectObjs(lqw);
    }

    private LambdaQueryWrapper<Classes> buildQueryWrapper(ClassesBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<Classes> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getClassYear() != null, Classes::getClassYear, bo.getClassYear());
        lqw.eq(bo.getClassNum() != null, Classes::getClassNum, bo.getClassNum());
        lqw.eq(bo.getTeacherId() != null, Classes::getTeacherId, bo.getTeacherId());
        lqw.eq(StringUtils.isNotBlank(bo.getAlias()), Classes::getAlias, bo.getAlias());
        lqw.eq(bo.getSchoolCampusId() != null, Classes::getSchoolCampusId, bo.getSchoolCampusId());
        return lqw;
    }

    /**
     * 新增班级管理
     */
    @Override
    public Boolean insertByBo(ClassesBo bo) {
        String result = "";
        //获取批量添加
        Object classdata = bo.getClassdata();
        Map<String, Integer> map = (Map<String, Integer>) classdata;

        if (bo.getClassYear() == null && map.size() == 0) {
            throw new ServiceException("至少选择一个年级来批量创建班级！");
        }
        if (map.size() == 0 && ((Map<?, ?>) classdata).size()==0) {
            Classes classes = new Classes();
            BeanUtils.copyProperties(bo, classes);
            Classes getclasses = findClassesList(classes);
            if (getclasses != null) {
                throw new ServiceException("当前校区" + classes.getClassYear() + "年" + classes.getClassNum() + "班已经存在");
            }
            baseMapper.insert(classes);

            List<Long> classTeachers = bo.getClassTeachers();//获取到所有教师id
            //把教师保存至对应的教师班级绑定表
            if (classTeachers != null && classTeachers.size() > 0) {
                for (Long classTeacher : classTeachers) {
                    TeacherClassesBo teacherClasses = new TeacherClassesBo();
                    teacherClasses.setClassesId(classes.getId());
                    teacherClasses.setTeacherId(classTeacher);
                    teacherClasses.setSchoolCampusId(bo.getSchoolCampusId());
                    this.teacherClassesService.insertByBo(teacherClasses);
                }
            }

            return true;
        }

        for (String key : map.keySet()) {
            // 循环遍历 创建班级
            for (int i = 1; i <= map.get(key); i++) {
                Classes classes = new Classes();
                classes.setSchoolCampusId(bo.getSchoolCampusId());
                classes.setClassNum(i);
                classes.setClassYear(Integer.valueOf(key));
                Classes getclasses = findClassesList(classes);
                if (getclasses != null) {
                    result += " " + key + "年" + i + "班";
                    continue;
                }
                baseMapper.insert(classes);
            }
        }
        if (result.length() > 0) {
            throw new ServiceException("已存在班级：" + result + "已忽略这些班级！");
        }

        return true;
    }

    /**
     * 修改班级管理
     */
    @Override
    public Boolean updateByBo(ClassesBo bo) {

        List<Long> classTeachers = bo.getClassTeachers();//获取到所有教师id
        //把教师保存至对应的教师班级绑定表
        teacherClassesService.deleteByClassId(bo.getId());
        if (classTeachers != null && classTeachers.size() > 0) {
            //修改教师绑定之前先把绑定数据清除
            for (Long classTeacher : classTeachers) {
                TeacherClassesBo teacherClasses = new TeacherClassesBo();
                teacherClasses.setClassesId(bo.getId());
                teacherClasses.setTeacherId(classTeacher);
                teacherClasses.setSchoolCampusId(bo.getSchoolCampusId());
                this.teacherClassesService.insertByBo(teacherClasses);
            }
        }
        Classes classes = new Classes();
        BeanUtils.copyProperties(bo, classes);
        return baseMapper.updateById(classes)>0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(Classes entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除班级管理
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public List<ClassesVo> getSchoolClasses(Long schoolCampusId) {
        MPJLambdaWrapper<Classes> mpj = JoinWrappers.lambda(Classes.class);

        LoginUser loginUser = LoginHelper.getLoginUser();
        UserType userType = UserType.getUserType(loginUser.getUserType());
        switch (userType) {
            case SYS_USER:

                break;
            case SCHOOLADMIN:

                break;
            case TEACHER:
                List<Object> t1 = this.teacherClassesService.findbyTeacherId(loginUser.getTeacherId());
                List<Object> t2 = this.findbyTeacherId(loginUser.getTeacherId());
                t1.addAll(t2);

                if (t1.size() > 0) {
                    mpj.selectAll(Classes.class)
                        .in(Classes::getId, t1);
                }else{
                    return null;
                }
//                    mpj.or().eq(Classes::getTeacherId,loginUser.getSysUser().getBindId());
                break;
            default:
                return null;
        }
        if (schoolCampusId != null && schoolCampusId != 0L) {
            mpj.eq(Classes::getSchoolCampusId, schoolCampusId);
        }
        mpj.orderByDesc(Classes::getClassYear).orderByAsc(Classes::getClassNum).logicDelToOn();
        List<Classes> classes = this.baseMapper.selectList(mpj);
        //遍历班级数据，并且对年份进行转换
        List<ClassesVo> classesDtolist = classes.stream().map(item -> {
            ClassesVo classesVo = new ClassesVo();
            if (item.getClassYear() != null && item.getClassYear() != 0L) {
                Map<Integer, String> map = getSchoolGrades(item.getSchoolCampusId());
                Map<Integer, String> schoolClasses = map.entrySet().stream()
                    .collect(Collectors.toMap(entry -> Integer.parseInt(String.valueOf(entry.getKey())), Map.Entry::getValue));

                classesVo.setClassName(schoolClasses.get(item.getClassYear().intValue()) + item.getClassNum() + "班");
                classesVo.setClassYear(item.getClassYear());
                classesVo.setId(item.getId());
            }
            return classesVo;
        }).collect(Collectors.toList());

        return classesDtolist;

    }

    @Override
    public Map<Integer, String> getSchoolGrades(Long schoolCampusId) {

        Campus schoolCampus = this.campusService.selectSchoolCampusById(schoolCampusId);
        if (schoolCampus == null) {
            throw new ServiceException("未找到校区");
        }
        Long campusNature = schoolCampus.getCampusNature();
        String type = SchoolType.getByCode(String.valueOf(campusNature)).getType();
        return SchoolUtils.getSchoolClassYear(type);
    }

    @Override
    public List<Object> findbyTeacherId(Long userId) {
        MPJLambdaWrapper<Classes> mpj = new MPJLambdaWrapper<Classes>();
        mpj.select(Classes::getId)
            .eq(StringUtils.isNotNull(userId), Classes::getTeacherId ,userId);
        return baseMapper.selectObjs(mpj);
    }

    @Override
    public Classes findClassesList(Classes classes) {
        //拼装查询条件
        LambdaQueryWrapper<Classes> queryWrapper = new LambdaQueryWrapper<>();

        //根据班级年份、班级号、校区、查询班级是否存在
        if (classes.getClassYear() != null && classes.getClassYear() != 0) {
            queryWrapper.eq(Classes::getClassYear, classes.getClassYear());

        }
        if (classes.getClassNum() != null && classes.getClassNum() != 0) {
            queryWrapper.eq(Classes::getClassNum, classes.getClassNum());

        }
        if (classes.getSchoolCampusId() != null && classes.getSchoolCampusId() != 0L) {
            queryWrapper.eq(Classes::getSchoolCampusId, classes.getSchoolCampusId());
        }

        return baseMapper.selectOne(queryWrapper);
    }



    @Override
    @Cacheable(value = "schoolClassesName", key = "#schoolCampusId")
    public Map<String, Integer> getSchoolClassesName(Long schoolCampusId) {
        Campus schoolCampus = this.campusService.selectSchoolCampusById(schoolCampusId);
        if (schoolCampus == null) {
            throw new ServiceException("未找到校区");
        }
        Long campusNature = schoolCampus.getCampusNature();

        String type = SchoolType.getByCode(String.valueOf(campusNature)).getType();

        return SchoolUtils.getSchoolClassName(type);
    }

    @Override
    public List<SchoolClassesTreeNodeBo> getSchoolClassesTreeNode() {


        LoginUser loginUser = LoginHelper.getLoginUser();
        UserType userType = UserType.getUserType(loginUser.getUserType());

        List<SchoolClassesTreeNodeBo> listfirstNode = new ArrayList<>();

        List<SysTenant> schoolList = new ArrayList<>();

        String tenantId = loginUser.getTenantId();

        SysTenantVo sysTenantVo = this.tenantService.queryByTenantId(tenantId);

        List<BindingSchools> bindingSchools = null;

        switch (userType) {
            case SYS_USER:
                //系统用户  获取到所有的学校
                schoolList = this.tenantService.findTenantList();

                for (SysTenant school : schoolList) {
                    SchoolClassesTreeNodeBo firstNode = new SchoolClassesTreeNodeBo();
                    firstNode.setLabel(school.getCompanyName());//tree 返回学校名称
                    firstNode.setSchoolId(school.getId());
                    Campus schoolCampus = new Campus();
                    schoolCampus.setTenantId(school.getTenantId());
                    //遍历所有学校拿到校区
                    List<Campus> schoolCampusList = this.campusService.findCampusList(schoolCampus);
                    schoolClassesNodes(listfirstNode, firstNode, schoolCampusList);

                }
                break;
            case SCHOOLADMIN:

                bindingSchools = this.bindingSchoolsService.findByTeacherId(loginUser.getTeacherId());
                List<Long> campusids = bindingSchools.stream()
                    .map(BindingSchools::getSchoolCampusId)
                    .collect(Collectors.toList());
                SchoolClassesTreeNodeBo firstNode = new SchoolClassesTreeNodeBo();
                firstNode.setLabel(sysTenantVo.getCompanyName());//tree 返回学校名称
                firstNode.setSchoolId(sysTenantVo.getId());
                List<Campus> schoolCampusNamesByIds = this.campusService.findSchoolCampusNamesByIds(campusids);
                schoolClassesNodes(listfirstNode, firstNode, schoolCampusNamesByIds);




                break;
            case TEACHER:
               // List<Long> teachercampusids = Arrays.asList(loginUser.getSysUser().getSchoolCampusIds().split(",")).stream().map(Long::valueOf).collect(Collectors.toList());
                // List<String> schoolCampus = Arrays.asList(loginUser.getSysUser().getSchoolCampusName().split(",")).stream().collect(Collectors.toList());

                bindingSchools = this.bindingSchoolsService.findByTeacherId(loginUser.getTeacherId());
                List<Long> teachercampusids = bindingSchools.stream()
                    .map(BindingSchools::getSchoolCampusId)
                    .collect(Collectors.toList());
                SchoolClassesTreeNodeBo teacherfirstNode = new SchoolClassesTreeNodeBo();
                teacherfirstNode.setLabel(sysTenantVo.getCompanyName());//tree 返回学校名称
                teacherfirstNode.setSchoolId(sysTenantVo.getId());
                List<Campus> teacherschoolCampusNamesByIds = this.campusService.findSchoolCampusNamesByIds(teachercampusids);
                schoolClassesNodes(listfirstNode, teacherfirstNode, teacherschoolCampusNamesByIds);
                break;
            default:
                return null;
        }


        return listfirstNode;
    }


    private void changeYearToName(List<ClassesVo> list) {
        list.stream().map(
            item -> {
                if (item.getClassYear() != null && item.getSchoolCampusId() != null) {
                    if (item.getClassYear() != 0L) {
//                            Map<Integer, String> schoolClasses = getSchoolGrades(item.getSchoolCampusId());
                        Map<Integer, String> map = getSchoolGrades(item.getSchoolCampusId());
                        Map<Integer, String> schoolClasses = map.entrySet().stream()
                            .collect(Collectors.toMap(entry -> Integer.parseInt(String.valueOf(entry.getKey())), Map.Entry::getValue));

                        item.setClassName(schoolClasses.get(item.getClassYear().intValue()));
                    }
                }

                return item;
            }
        ).collect(Collectors.toList());
    }



    //对 节点 2 ，3 ，4 进行了封装
    private void schoolClassesNodes(List<SchoolClassesTreeNodeBo> listfirstNode, SchoolClassesTreeNodeBo firstNode, List<Campus> schoolCampusList) {
        List<SchoolClassesTreeNodeBo> listsecondNode = new ArrayList<>();
        for (Campus campus : schoolCampusList) {
            SchoolClassesTreeNodeBo secondNode = new SchoolClassesTreeNodeBo();
            secondNode.setLabel(campus.getCampusName());//tree 返回学校名称
            secondNode.setSchoolCampusId(campus.getCampusId());
            //根据校区拿到所有班级
            List<ClassesVo> schoolClasses = this.getSchoolClasses(campus.getCampusId());
            //拿到三级节点数据
            Map<Integer, String> schoolGrades = getSchoolGrades(campus.getCampusId());
            List<SchoolClassesTreeNodeBo> listthirdNodes = new ArrayList<>();
            //开始组装三级节点 遍历map集合
            for (Integer key : schoolGrades.keySet()) {
                boolean b =schoolClasses!=null&& schoolClasses.stream().anyMatch(s -> s.getClassYear().equals(key));
                if(b){

                    SchoolClassesTreeNodeBo thirdNode = new SchoolClassesTreeNodeBo();
                    thirdNode.setLabel(schoolGrades.get(key) + key + "级");
                    thirdNode.setClassYear(key);
                    thirdNode.setSchoolCampusId(campus.getCampusId());
                    List<ClassesVo> getclasses = new ArrayList<ClassesVo>();
                    //四级节点数据 一年级1班 获取到所有的班级
                    for (ClassesVo classes : schoolClasses) {
                        if (classes.getClassYear().equals(key)) {
                            getclasses.add(classes);
                        }
                    }
                    //遍历拿到的班级数据
                    if (getclasses.size() > 0) {
                        List<SchoolClassesTreeNodeBo> listfourthNodes = new ArrayList<>();
                        for (ClassesVo classess : getclasses) {
                            SchoolClassesTreeNodeBo fourthNode = new SchoolClassesTreeNodeBo();
                            fourthNode.setClassesId(String.valueOf(classess.getId()));
                            fourthNode.setLabel(classess.getClassName());
                            listfourthNodes.add(fourthNode);
                        }
                        thirdNode.setChildren(listfourthNodes);
                    }

                    listthirdNodes.add(thirdNode);
                }
            }
            secondNode.setChildren(listthirdNodes);// 三级集合添加单 二级节点 childred
            listsecondNode.add(secondNode);// 二级节点添加到集合中    ##
            //通过校区id拿到所有年级
        }
        firstNode.setChildren(listsecondNode);//一级节点添加子集
        listfirstNode.add(firstNode);//一级节点添加到集合中         #####
    }





}
